package cn.com.jonpad.demo08_cache_01.service;

import cn.com.jonpad.demo08_cache_01.entity.Emploee;
import cn.com.jonpad.demo08_cache_01.rpository.EmploeeRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Optional;

@Service
@Slf4j
@CacheConfig(cacheNames = "emp")
public class EmploeeService {

	@Autowired
	EmploeeRepository repository;

	/**
	 * 使用<b>@Cacheable</b>注解，将方法运行结果进行缓存
	 *       cacheNames/value：指定缓存组件的名字;将方法的返回结果放在哪个缓存中，是数组的方式，可以指定多个缓存；
	 * 
	 *       key：缓存数据使用的key；可以用它来指定。默认是使用方法参数的值  1-方法的返回值
	 *               编写SpEL； #i d;参数id的值   #a0  #p0  #root.args[0]
	 *               getEmp[2]
	 * 
	 *       keyGenerator：key的生成器；可以自己指定key的生成器的组件id
	 *               key/keyGenerator：二选一使用;
	 * 
	 * 
	 *       cacheManager：指定缓存管理器；或者cacheResolver指定获取解析器
	 * 
	 *       condition：指定符合条件的情况下才缓存；
	 *               ,condition = "#id>0"
	 *           condition = "#a0>1"：第一个参数的值》1的时候才进行缓存
	 * 
	 *       unless:否定缓存；当unless指定的条件为true，方法的返回值就不会被缓存；可以获取到结果进行判断
	 *               unless = "#result == null"
	 *               unless = "#a0==2":如果第一个参数的值是2，结果不缓存；
	 *       sync：是否使用异步模式 @Cacheable(sync=true) does not support unless attribute
	 * @param id
	 * @return
	 */
	@Cacheable(key = "#id"/*keyGenerator = "cacheConfigKeyGenerator"*//*,condition = "#a0>0"*//*,unless = "#a0==2"*/,sync = true)
	public Optional<Emploee> getOne(Long id){
		log.info("查询员工");
		return repository.findById(id);
	}

	/**
	 * 由于更新和读取在需要同步更新的情况向，需要保证@Cacheable和@CachePut的Key值相同
	 * @param emp
	 * @return
	 */
	@Transactional(rollbackFor = Exception.class)
	@CachePut(key = "#result.id")
	public Emploee updateEmp(Emploee emp){
		Optional<Emploee> one = repository.findById(emp.getId());
		if (one.isPresent()) {
			Emploee emploee = one.get();
			emploee.setUsername(emp.getUsername());
			repository.saveAndFlush(emploee);
		}
		return one.get();
	}

	/**
	 * 删除时清除 缓存
	 * @param id
	 */
	@Transactional(rollbackFor = Exception.class)
	@CacheEvict(key = "#id")
	public void delete(Long id){
		repository.deleteById(id);
	}

	/**
	 * 清楚所有缓存
	 * beforeInvocation 指定在方法执行前进行缓存操作，默认在方法执行后进行
	 */
	@CacheEvict(allEntries = true,beforeInvocation = true)
	public void rmAll(){
		log.info("清楚所有缓存");
	}


	@Caching(
			cacheable = {
					@Cacheable(key = "#name")
			},
			put = {
					@CachePut(key = "#result.id"),
					@CachePut(key = "#result.username")
			}
	)
	public Emploee getEmpByName(String name){
		log.info("使用名字查询员工");
		return repository.findByUsername(name);
	}
}
